﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;

namespace YJKRevitCode.ShortPathSuite
{
	public class BaseWapMapCalculater<X> where X : BaseEndPointPacker
	{
		protected BaseWapMapCalculater()
		{
			this.m_useCalculaterDel = new GenericShortWayCalculatDel<X>(this.BaseCalculateMethod);
		}

		public BaseWapMapCalculater(List<BaseCurveBean> lstInputAllCanGoCurve, List<BaseCurveBean> lstInputAllCanNotGoCurve, MidPointUsefulDel inputDel)
		{
			this.m_useCalculaterDel = new GenericShortWayCalculatDel<X>(this.BaseCalculateMethod);
			this.m_lstAllCanNotGoCurves = new List<BaseCurveBean>();
			this.m_lstAllCanNotGoCurves.AddRange(lstInputAllCanNotGoCurve);
			this.m_lstAllCanGoBoundaryCurves = new List<BaseCurveBean>();
			this.m_lstAllCanGoBoundaryCurves.AddRange(lstInputAllCanGoCurve);
			List<XYZPoint> list = new List<XYZPoint>();
			List<Line> lstLine = new List<Line>();
			int num = 0;
			this.m_useMidPointDel = inputDel;
			foreach (BaseCurveBean baseCurveBean in this.m_lstAllCanGoBoundaryCurves)
			{
				for (int i = 0; i < 2; i++)
				{
					list.Add(new XYZPoint(baseCurveBean.ThisCurve.GetEndPoint(i), num));
				}
				num++;
			}
			this.CalculaterLinkWay(list, lstLine);
		}

		public void SetStartPoint(X inputStartPoint)
		{
			this.SetPoint(inputStartPoint, 0);
		}

		public void SetEndPoint(X inputEndPoint)
		{
			this.SetPoint(inputEndPoint, 1);
		}

		public bool TryCalculate(out ResultBean result)
		{
			result = null;
			List<XYZ> lstPoints;
			bool flag;
			this.CalculatePath(out lstPoints, out flag);
			if (flag)
			{
				result = new ResultBean(this.m_lstEndPoints[0], this.m_lstEndPoints[1], lstPoints);
			}
			return flag;
		}

		protected void CalculaterLinkWay(List<XYZPoint> lstXYZPoint, List<Line> lstLine)
		{
			for (int i = 0; i < lstXYZPoint.Count; i++)
			{
				XYZPoint xyzpoint = lstXYZPoint[i];
				for (int j = i + 1; j < lstXYZPoint.Count; j++)
				{
					XYZPoint xyzpoint2 = lstXYZPoint[j];
					if (xyzpoint.nFlag != xyzpoint2.nFlag && !xyzpoint.point.IsAlmostEqualTo(xyzpoint2.point))
					{
						Line item = Line.CreateBound(xyzpoint.point, xyzpoint2.point);
						lstLine.Add(item);
					}
				}
			}
			this.GetEffectiveLine(lstLine);
		}

		protected void CalculatePath(out List<XYZ> lstPoints, out bool returnValue)
		{
			List<Curve> tempCurve = this.GetTempCurve(this.m_lstWayMap, this.m_lstAllCanGoBuildingLinkCurve, this.m_lstAllCanGoBoundaryCurves);
			returnValue = false;
			lstPoints = null;
			X x = this.m_lstEndPoints[0];
			XYZ useEndPoint = x.UseEndPoint;
			X x2 = this.m_lstEndPoints[1];
			if (useEndPoint.IsAlmostEqualTo(x2.UseEndPoint, this.m_dUseTolerance))
			{
				return;
			}
			X x3 = this.m_lstEndPoints[0];
			XYZ useEndPoint2 = x3.UseEndPoint;
			X x4 = this.m_lstEndPoints[1];
			Line item = Line.CreateBound(useEndPoint2, x4.UseEndPoint);
			List<BaseCurveBean> list = this.SetPointGetEffectiveLine(new List<Line>
			{
				item
			});
			if (list.Count != 0)
			{
				returnValue = true;
				List<XYZ> list2 = new List<XYZ>();
				List<XYZ> list3 = list2;
				X x5 = this.m_lstEndPoints[0];
				list3.Add(x5.UseEndPoint);
				List<XYZ> list4 = list2;
				X x6 = this.m_lstEndPoints[1];
				list4.Add(x6.UseEndPoint);
				lstPoints = list2;
				return;
			}
			if (this.m_useCalculaterDel == null)
			{
				this.m_useCalculaterDel = new GenericShortWayCalculatDel<X>(this.BaseCalculateMethod);
			}
			returnValue = this.m_useCalculaterDel(this.m_lstEndPoints[0], this.m_lstEndPoints[1], tempCurve, out lstPoints);
		}

		private List<Curve> GetTempCurve(List<List<BaseCurveBean>> lstWayMap, List<BaseCurveBean> lstAllCanGoBuildingLinkCurve, List<BaseCurveBean> lstAllCanGoBoundaryCurves)
		{
			List<Curve> list = new List<Curve>();
			foreach (List<BaseCurveBean> list2 in lstWayMap)
			{
				foreach (BaseCurveBean baseCurveBean in list2)
				{
					list.Add(baseCurveBean.ThisCurve);
				}
			}
			foreach (BaseCurveBean baseCurveBean2 in lstAllCanGoBuildingLinkCurve)
			{
				list.Add(baseCurveBean2.ThisCurve);
			}
			foreach (BaseCurveBean baseCurveBean3 in lstAllCanGoBoundaryCurves)
			{
				list.Add(baseCurveBean3.ThisCurve);
			}
			return list;
		}

		private void SetPoint(X inputEndPoint, int index)
		{
			this.m_lstEndPoints[index] = inputEndPoint;
			List<Line> list = new List<Line>();
			List<XYZ> list2 = new List<XYZ>();
			Dictionary<X, List<BaseCurveBean>> dictionary;
			if (index == 0)
			{
				dictionary = this.m_dicStartPointCurves;
			}
			else
			{
				dictionary = this.m_dicEndPointCurves;
			}
			if (dictionary.ContainsKey(inputEndPoint))
			{
				this.JudgeContains(index, dictionary, inputEndPoint);
				return;
			}
			foreach (BaseCurveBean baseCurveBean in this.m_lstAllCanGoBoundaryCurves)
			{
				list2.Add(baseCurveBean.ThisCurve.GetEndPoint(0));
			}
			foreach (XYZ xyz in list2)
			{
				if (!inputEndPoint.UseEndPoint.IsAlmostEqualTo(xyz, this.m_dUseTolerance))
				{
					Line item = Line.CreateBound(inputEndPoint.UseEndPoint, xyz);
					list.Add(item);
				}
			}
			dictionary.Add(inputEndPoint, this.SetPointGetEffectiveLine(list));
			this.JudgeContains(index, dictionary, inputEndPoint);
		}

		private void JudgeContains(int useIndex, Dictionary<X, List<BaseCurveBean>> inputDicEndPointCurves, X inputEndPoint)
		{
			if (inputDicEndPointCurves.ContainsKey(inputEndPoint))
			{
				this.m_lstWayMap[useIndex] = inputDicEndPointCurves[inputEndPoint];
			}
		}

		private List<BaseCurveBean> SetPointGetEffectiveLine(List<Line> lstLine)
		{
			List<BaseCurveBean> list = new List<BaseCurveBean>();
			List<Line> newLstLine = this.QuickCurveCheck(lstLine);
			return this.DetailFindUseCurve(newLstLine);
		}

		private List<BaseCurveBean> DetailFindUseCurve(List<Line> newLstLine)
		{
			List<BaseCurveBean> list = new List<BaseCurveBean>();
			bool flag = false;
			foreach (Line line in newLstLine)
			{
				flag = false;
				XYZ inputPoint = line.Evaluate(0.5, true);
				if (this.m_useMidPointDel == null || this.m_useMidPointDel(inputPoint))
				{
					foreach (BaseCurveBean baseCurveBean in this.m_lstAllCanGoBoundaryCurves)
					{
						IntersectionResultArray tempResultArray;
						SetComparisonResult tempResult = line.Intersect(baseCurveBean.ThisCurve, out tempResultArray);
						flag = this.JudgeIntersect(tempResult, tempResultArray, line.GetEndPoint(0), line.GetEndPoint(1));
						if (!flag)
						{
							break;
						}
					}
					if (flag)
					{
						list.Add(new BaseCurveBean(line, true, false));
					}
				}
			}
			return list;
		}

		private void GetEffectiveLine(List<Line> lstLine)
		{
			List<BaseCurveBean> collection = this.SetPointGetEffectiveLine(lstLine);
			this.m_lstAllCanGoBuildingLinkCurve.AddRange(collection);
		}

		private List<Line> QuickCurveCheck(List<Line> lstLine)
		{
			List<Line> list = new List<Line>();
			bool flag = false;
			foreach (Line line in lstLine)
			{
				flag = false;
				foreach (BaseCurveBean baseCurveBean in this.m_lstAllCanNotGoCurves)
				{
					SetComparisonResult setComparisonResult = line.Intersect(baseCurveBean.ThisCurve);
					if (setComparisonResult == SetComparisonResult.Overlap)
					{
						flag = false;
						break;
					}
					flag = true;
				}
				if (flag)
				{
					list.Add(line);
				}
			}
			return list;
		}

		private bool JudgeIntersect(SetComparisonResult tempResult, IntersectionResultArray tempResultArray, XYZ startPoint, XYZ endPoint)
		{
			bool result = true;
            if ((int)tempResult != 4 && (int)tempResult == 8 && !startPoint.IsAlmostEqualTo(tempResultArray.get_Item(0).XYZPoint, this.m_dUseTolerance) && !endPoint.IsAlmostEqualTo(tempResultArray.get_Item(0).XYZPoint, this.m_dUseTolerance))
			{
				result = false;
			}
			return result;
		}

		private bool BaseCalculateMethod(X startPoint, X endPoint, List<Curve> lstAllGoCurve, out List<XYZ> lstPoints)
		{
			return this.m_useCalculater.TryCalculateShortestPath(startPoint.UseEndPoint, endPoint.UseEndPoint, lstAllGoCurve, out lstPoints);
		}

		protected GenericShortWayCalculatDel<X> m_useCalculaterDel;

		protected MidPointUsefulDel m_useMidPointDel;

		protected double m_dUseTolerance = 1E-05;

		protected List<X> m_lstEndPoints = new List<X>
		{
			default(X),
			default(X)
		};

		protected List<List<BaseCurveBean>> m_lstWayMap = new List<List<BaseCurveBean>>
		{
			null,
			null
		};

		protected UseGraphCalculater m_useCalculater = new UseGraphCalculater();

		protected List<BaseCurveBean> m_lstAllCanGoBoundaryCurves = new List<BaseCurveBean>();

		protected List<BaseCurveBean> m_lstAllCanNotGoCurves = new List<BaseCurveBean>();

		protected List<BaseCurveBean> m_lstAllCanGoBuildingLinkCurve = new List<BaseCurveBean>();

		protected Dictionary<X, List<BaseCurveBean>> m_dicStartPointCurves = new Dictionary<X, List<BaseCurveBean>>();

		protected Dictionary<X, List<BaseCurveBean>> m_dicEndPointCurves = new Dictionary<X, List<BaseCurveBean>>();
	}
}
